/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-05-29     甘泽       the first version
 */

#include <rtthread.h>
#include <sensor_m8n.h>
#include <bsp_usart.h>

static rt_device_t m8n_gps_dev = RT_NULL;

static uint8_t *m8n_nmea0183_buffer = RT_NULL; /* 用于存储一帧NMEA0183的帧数据 */
static uint16_t m8n_nmea0183_buffer_len = 0;   /* 记录该帧的长度 */

/// @brief m8n 设备初始化
/// @return 成功返回0
static int bsp_m8n_init();

/* 设备接口 */
static rt_err_t rt_m8n_gps_open(rt_device_t dev, rt_uint16_t oflag);
static rt_err_t rt_m8n_gps_close(rt_device_t dev);
static rt_size_t rt_m8n_gps_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
static rt_size_t rt_m8n_gps_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
static rt_err_t rt_m8n_gps_control(rt_device_t dev, int cmd, void *args);

int rt_m8n_gps_register(void)
{
    static rt_uint8_t m8n_gps_register_passed = 0;
    if (m8n_gps_register_passed != 0)
        return RT_EOK;

    /* construct device */
    m8n_gps_dev = rt_device_create(RT_Object_Class_Device, 0);
    if (m8n_gps_dev == RT_NULL)
    {
        rt_kprintf("error happened when create m8n gps device\n");
        return RT_ENOMEM;
    }

    /* set device function pointer */
    m8n_gps_dev->init = RT_NULL;
    m8n_gps_dev->open = rt_m8n_gps_open;
    m8n_gps_dev->close = rt_m8n_gps_close;
    m8n_gps_dev->read = rt_m8n_gps_read;
    m8n_gps_dev->write = rt_m8n_gps_write;
    m8n_gps_dev->control = rt_m8n_gps_control;

    /* register device */
    int rslt = rt_device_register(m8n_gps_dev, M8N_DEV_NAME, RT_DEVICE_FLAG_RDWR);
    if (rslt != RT_EOK)
    {
        rt_kprintf("error happened when register bmi270 accelerator device, rslt = %d\n", rslt);
    }

    rslt = bsp_m8n_init();
    if (rslt == RT_EOK)
    {
        m8n_gps_register_passed = 1;
    }

    return rslt;
}

int update_nmea_data(uint8_t *buf, uint16_t data_len)
{
    if (buf == RT_NULL)
        return -1;

    m8n_nmea0183_buffer = buf;
    m8n_nmea0183_buffer_len = data_len;

    return RT_EOK;
}

static int bsp_m8n_init()
{
    bsp_gps_uart_init();

    return RT_EOK;
}

static rt_err_t rt_m8n_gps_open(rt_device_t dev, rt_uint16_t oflag)
{
    if (dev == RT_NULL || dev != m8n_gps_dev)
    {
        rt_kprintf("m8n GPS open failed for device pointer not correct\n");
        return RT_ERROR;
    }

    UART_HandleTypeDef *gps_handle = bsp_gps_handle();
    if (gps_handle)
        __HAL_UART_ENABLE(gps_handle);

    return RT_EOK;
}

static rt_err_t rt_m8n_gps_close(rt_device_t dev)
{
    if (dev == RT_NULL || dev != m8n_gps_dev)
    {
        rt_kprintf("m8n GPS close failed for device pointer not correct\n");
        return RT_ERROR;
    }

    UART_HandleTypeDef *gps_handle = bsp_gps_handle();
    if (gps_handle)
        __HAL_UART_DISABLE(gps_handle);

    return RT_EOK;
}

static rt_size_t rt_m8n_gps_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
    if (dev == RT_NULL || dev != m8n_gps_dev)
    {
        rt_kprintf("m8n GPS read failed for device pointer not correct\n");
        return RT_ERROR;
    }

    /* 获得串口接收到的buffer */
    /* 串口中断判断接收到了NMEA0183一帧，已经调用使用 update_nmea_data 函数获取buffer和长度*/
    if (m8n_nmea0183_buffer == RT_NULL)
    {
        return RT_ERROR; /* 等待有一帧GPS数据 */
    }

    /* 对buffer进行解析得到GPS数据 */
    lwgps_process((lwgps_t *)buffer, m8n_nmea0183_buffer, m8n_nmea0183_buffer_len);

    /* 将buffer指针和长度重置 */
    m8n_nmea0183_buffer = RT_NULL;
    m8n_nmea0183_buffer_len = 0;

    /* 重新开启串口接收中断 */
    UART_HandleTypeDef *gps_handle = bsp_gps_handle();
    if (gps_handle)
        __HAL_UART_ENABLE_IT(gps_handle, UART_IT_RXNE);

    return sizeof(lwgps_t);
}

static rt_size_t rt_m8n_gps_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
    if (dev == RT_NULL || dev != m8n_gps_dev)
    {
        rt_kprintf("m8n GPS write failed for device pointer not correct\n");
        return RT_ERROR;
    }

    UART_HandleTypeDef *gps_handle = bsp_gps_handle();
    if (gps_handle)
        HAL_UART_Transmit(gps_handle, (uint8_t *)buffer, size, size);

    return size;
}

static rt_err_t rt_m8n_gps_control(rt_device_t dev, int cmd, void *args)
{
    if (dev == RT_NULL || dev != m8n_gps_dev)
    {
        rt_kprintf("m8n GPS control failed for device pointer not correct\n");
        return RT_ERROR;
    }

    // int *value = args;
    int rslt = 0;
    switch (cmd)
    {
    case M8N_CMD_SET_ODR:
        break;

    default:
        break;
    }

    return rslt;
}
